package utils

import (
	"GinBlog/models"
	"GinBlog/models/request"
	"errors"
	"time"

	jwt "github.com/golang-jwt/jwt/v5"
	"github.com/google/uuid"
)

type JWT struct {
	SigningKey []byte
}

func NewJWT() *JWT {
	return &JWT{
		SigningKey: []byte("blog_key_20251027"),
	}
}

func (j JWT) CreateClaims(userId uint, username string) request.Claims {
	return request.Claims{
		RegisteredClaims: jwt.RegisteredClaims{
			Audience:  jwt.ClaimStrings{"GinBlog"},                             // 受众
			NotBefore: jwt.NewNumericDate(time.Now().Add(-1000)),               // 签名生效时间
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(30 * 24 * time.Hour)), // 过期时间 30天
			Issuer:    "ginblog",                                               // 签名的发行者
		},
		Uuid:     uuid.New(),
		UserID:   userId,
		Username: username,
	}
}

func (j *JWT) CreateToken(claims request.Claims) (string, error) {
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(j.SigningKey)
}

func (j *JWT) ParseToken(tokenString string) (claims *request.Claims, err error) {
	token, err := jwt.ParseWithClaims(tokenString, &request.Claims{}, func(token *jwt.Token) (interface{}, error) {
		return j.SigningKey, nil
	})

	if err != nil {
		return nil, err
	}

	if claims, ok := token.Claims.(*request.Claims); ok && token.Valid {
		return claims, nil
	}

	return nil, errors.New("invalid token")
}

func LoginToken(user *models.User) (token string, claims request.Claims, err error) {
	j := NewJWT()
	claims = j.CreateClaims(user.ID, user.Username)
	token, err = j.CreateToken(claims)
	return
}
